<?php

namespace App\Http\Controllers\PartnerApi;

use App\Enums\AssetKeyStatus;
use App\Enums\AssetStatus;
use App\Enums\ExchangeChannel;
use App\Enums\TransferSource;
use App\Http\Controllers\Controller;
use App\Jobs\TransferJob;
use App\Models\Asset;
use App\Models\FrontendUser;
use App\Models\Product;
use App\Models\ProductConfig;
use App\Models\TransferRecord;
use App\Services\WalletService;
use Arr;
use Illuminate\Validation\ValidationException;

class TZSController extends Controller
{
    /** @var WalletService */
    private $walletService;

    /**
     * HezhiController constructor.
     */
    public function __construct(WalletService $walletService)
    {
        $this->walletService = $walletService;
    }

    /** 查询商品存证 */
    public function listProductTokens()
    {
        $data = request()->get('data', []);
        if (!Arr::get($data, 'commodityNum')) {
            return $this->failResponse(1001, '参数 commodityNum 未找到');
        }
        $limit = Arr::get($data, 'pageSize', 10);
        $page = Arr::get($data, 'pageNum', 1);
        if ($limit > 1000) {
            return $this->failResponse(1001, '每次最多查询1000条');
        }
        /** @var Product $product */
        $product = Product::query()
            ->where('agent_id', request()->agent_id)
            ->where('contract_address', Arr::get($data, 'commodityNum'))
            ->first();
        if (!$product) {
            return $this->failResponse(1003, '商品未找到');
        }
        $isLocked = $product->configs()
            ->where('config_key', ProductConfig::IS_LOCKED)
            ->value('config_value');
        if (!$isLocked) {
            return $this->failResponse(1004, '商品未锁定，无法上架到交易所');
        }
        $exchangeChannel = $product->configs()
            ->where('config_key', ProductConfig::EXCHANGE_CHANNEL)
            ->value('config_value');
        if ($exchangeChannel && ExchangeChannel::HEZHI()->isNot($exchangeChannel)) {
            return $this->failResponse(1004, '交易渠道设置错误，请将交易渠道设置为天知所');
        }

        //查询资产持有列表
        $assetQuery = Asset::query()
            ->with('user')
            ->where('contract_address', $product->contract_address)
            ->where('asset_status', AssetStatus::HOLD);
        $total = $assetQuery->count();
        $assets = $assetQuery
            ->offset($limit * ($page - 1))
            ->limit($limit)
            ->get();

        $list = [];
        foreach ($assets as $asset) {
            if (!$asset->cert_sn) {
                return $this->failResponse(1005, '资产证书编号同步未完成，无法上架到交易所');
            }
            $list[] = [
                'account' => $asset->user->wallet_address,
                'imgurl' => $product->logo_url,
                'assetToken' => $asset->token_id,
                'assetNum' => $asset->cert_sn,
            ];
        }

        $data = [
            'assetList' => $list,
            'pageNum' => $page,
            'pageSize' => $limit,
            'total' => $total,
            'totalPage' => ceil($total / $limit),
        ];

        return $this->successResponse($data);
    }

    /** 用户注册 */
    public function register()
    {
        $data = request()->get('data', []);
        $phoneNo = Arr::get($data, 'phone');
        if (!$phoneNo) {
            return $this->failResponse(1001, '参数 phone 未找到');
        }
        $user = FrontendUser::query()
            ->where('mobile', $phoneNo)
            ->where('agent_id', Arr::get($data, 'agent_id'))
            ->first();
        if (!$user) {
            $walletAddress = $this->walletService->openWallet($phoneNo);
            $user = new FrontendUser();
            $user->mobile = $phoneNo;
            $user->nickname = '';
            $user->agent_id = request()->agent_id;
            $user->password = '';
            $user->wallet_address = $walletAddress;
            $user->save();
        }

        return $this->successResponse([
            'account' => $user->wallet_address,
            'phone' => $phoneNo,
        ]);
    }

    /** 资产检查 */
    public function checkForTrade()
    {
        try {
            $data = request()->get('data', []);
            \Validator::validate($data, [
                'account' => 'required',
                'commodityNum' => 'required',
                'assetToken' => 'required',
            ]);
        } catch (ValidationException $e) {
            return $this->failResponse(1001, sprintf('参数 %s 未找到', implode(',', array_keys($e->errors()))));
        }
        /** @var Asset $asset */
        $asset = Asset::query()
            ->where('contract_address', Arr::get($data, 'commodityNum'))
            ->where('token_id', Arr::get($data, 'assetToken'))
            ->where('asset_status', AssetStatus::HOLD)
            ->first();
        if (!$asset) {
            return $this->failResponse(1001, '资产未找到');
        }
        if ($asset->user->wallet_address != Arr::get($data, 'account')) {
            return $this->failResponse(1001, '资产不属于卖方');
        }
        //判断权益兑换状态
        if ($asset->asset_key && $asset->asset_key->status->is(AssetKeyStatus::USED)) {
            //权益码已使用
            return $this->failResponse(1001, '权益码已使用');
        }

        return $this->successResponse([
            'result' => 1,
        ]);
    }

    /** 资产交易 */
    public function trade()
    {
        try {
            request()->validate([
                'buy_account' => 'required',
                'sell_account' => 'required',
                'commodity_code' => 'required',
                'certificate_code' => 'required',
                'certificate_number' => 'required',
                'trade_chain_code' => 'required',
                'return_url' => 'required',
            ]);
        } catch (ValidationException $e) {
            return $this->failResponse(1001, sprintf('参数 %s 未找到', implode(',', array_keys($e->errors()))));
        }
        $transferSn = request()->trade_chain_code;
        $existRecord = TransferRecord::query()
            ->where('source', TransferSource::HE_ZHI)
            ->where('transfer_sn', $transferSn)
            ->first();
        if ($existRecord) {
            return $this->failResponse(1001, 'trade_chain_code已存在 ，请不要重复请求');
        }
        $buyer = FrontendUser::query()->where('wallet_address', request()->buy_account)->where('agent_id', request()->agent_id)->first();
        if (!$buyer) {
            return $this->failResponse(1001, '无效的买方账号');
        }
        $seller = FrontendUser::query()->where('wallet_address', request()->sell_account)->where('agent_id', request()->agent_id)->first();
        if (!$seller) {
            return $this->failResponse(1001, '无效的卖方账号');
        }
        $asset = Asset::query()
            ->where('contract_address', request()->commodity_code)
            ->where('token_id', request()->certificate_code)
            ->where('asset_status', AssetStatus::HOLD)
            ->first();
        if (!$asset) {
            return $this->failResponse(1001, '资产未找到');
        }
        if ($asset->user_id != $seller->id) {
            return $this->failResponse(1001, '资产不属于卖方');
        }
        $record = new TransferRecord();
        $record->agent_id = request()->agent_id;
        $record->asset_id = $asset->id;
        $record->to_user_id = $buyer->id;
        $record->source = TransferSource::HE_ZHI;
        $record->transfer_sn = $transferSn;
        $record->source_params = json_encode(request()->all());
        $record->save();

        TransferJob::dispatch($record);

        return $this->successResponse([]);
    }

    private function failResponse($code, $msg)
    {
        return [
            'code' => 500,
            'message' => $msg,
            'data' => [],
        ];
    }

    private function successResponse($data)
    {
        return [
            'code' => 200,
            'message' => 'success',
            'data' => $data,
        ];
    }
}
